import 'package:flutter/material.dart';

import '../../dao/ImGroupDao.dart';
import '../../dao/ImGroupUserDao.dart';
import '../../dao/ImSessionDao.dart';
import '../../pojo/ImPojo.dart';
import '../../service/ImMessageService.dart';
import '../../socket/dto/business/SendData.dart';
import '../../socket/service/RpcSendDataService.dart';
import '../../util/ImConstant.dart';
import '../../util/ImSingleton.dart';
import '../view/model/DataChangeListener.dart';

class SessionListModel {

  final DataChangeStateListener<StatefulWidget, ImSession> messageDataChangeListener;

  SessionListModel({ required this.messageDataChangeListener});

  int _hotMessageTotal = 0;

  Future<List<ImSession>> loadData(String userId) async {
    print("SessionListModel load!!");
    var sessionDao = ImSessionDao();
    var startDate = DateTime.now().add(const Duration(days: -ImConstant.IM_SESSION_SHOW_DAYS));
    List<ImSession> sessions = await sessionDao.getByUserIdAndTimeAndSize(userId, startDate, 0, 500);
    if (sessions.isNotEmpty) {
      for (var session in sessions) {
        await sessionDao.loadGroupInfo(session);
      }
      sessionDao.sort(sessions);
    }

    _hotMessageTotal = sessions.map((session)=>session.hotMessageTotal??0).reduce((value, v) => value + v);

    return sessions??[];
  }

  void addSession(ImSession session) {
    if (has(session)) return;
    messageDataChangeListener.addFirst(session);
    _hotMessageTotal = _calacHotMessageTotal();
  }

  void changeSession(ImSession session) {
    print("changeSession, ${session.id}");
    messageDataChangeListener.updateData(session);
    this._hotMessageTotal = _calacHotMessageTotal();
  }

  void hideSession(ImSession session) async {
    final sessionDao = ImSessionDao();
    session.updateTime = DateTime.now().add(const Duration(days: -15));
    await sessionDao.batchUpdates(session.currentUserId!, [session]);

    messageDataChangeListener.deleteData(session);

     _hotMessageTotal = _calacHotMessageTotal();
  }

  Future<void> deleteSession(ImSession session) async {
    final messageService = ImMessageService();
    final sessionDao = ImSessionDao();

    await messageService.cleanMessage(session.currentUserId!, session.id!);

    session.status = ImSessionStatus.disable;
    session.updateTime = DateTime.now();
    await sessionDao.batchUpdates(session.currentUserId!, [session]);

    messageDataChangeListener.deleteData(session);

    _hotMessageTotal = _calacHotMessageTotal();
  }

  Future<void> sessionTop(ImSession session, bool isTop) async {
    var sessionDao = ImSessionDao();
    var groupUserDao = ImGroupUserDao();
    var groupDao = ImGroupDao();

    var rpcMessageService = RpcMessageService();
    var userId = ImSingleton.getInstance().session.userId!;

    if (session.groupCode != null) { // 群会话
      ImGroup? imGroup = await groupDao.getByCodeAndUserId(session.groupCode!, userId);
      ImGroupUser groupUser = imGroup!.currentGroupUser!;
      groupUser.isTop = isTop;
      groupUser.updateTime = DateTime.now();
      await groupUserDao.batchUpdates([groupUser].toSet());
    } else {
      if (session.fromUserId!.compareTo(session.toUserId!) >= 0) {
        session.isTop = isTop;
      } else {
        session.isTop2 = isTop;
      }
      session.updateTime = DateTime.now();
    }

    var key = session.groupCode != null ? session.groupCode : session.toUserId;
    var dataChangeReq = DataChangeReq(type: DataType.session,
        subType: DataSubType.s_ed_top,
        value: isTop.toString(),
        key: key!);
    await rpcMessageService.sendDataChange(dataChangeReq);

    await sessionDao.batchUpdates(userId, [session]);
    changeSession(session);
  }

  Future<void> sessionDisturb(ImSession session, bool isDisturb) async {
    var sessionDao = ImSessionDao();
    var groupUserDao = ImGroupUserDao();
    var groupDao = ImGroupDao();
    var rpcMessageService = RpcMessageService();
    var userId = ImSingleton.getInstance().session.userId!;
    if (session.groupCode != null) { // 群会话
      ImGroup? imGroup = await groupDao.getByCodeAndUserId(session.groupCode!, userId);
      ImGroupUser groupUser = imGroup!.currentGroupUser!;
      groupUser.isDisturb = isDisturb;
      groupUser.updateTime = DateTime.now();
      await groupUserDao.batchUpdates([groupUser].toSet());
    } else {
      if (session.fromUserId!.compareTo(session.toUserId!) >= 0) {
        session.isDisturb = isDisturb;
      } else {
        session.isDisturb2 = isDisturb;
      }
      session.updateTime = DateTime.now();
    }

    var key = session.groupCode != null ? session.groupCode : session.toUserId;
    var dataChangeReq = DataChangeReq(type: DataType.session,
        subType: DataSubType.s_ed_disturb,
        value: isDisturb.toString(),
        key: key!);
    await rpcMessageService.sendDataChange(dataChangeReq);

    await sessionDao.batchUpdates(userId, [session]);
    changeSession(session);
  }

  Future<void> reload(String userId) async {
    print("SessionListCubit reload!!");
    await loadData(userId);
  }

  void increaseHotMessageTotal(int total) {
    _hotMessageTotal = _calacHotMessageTotal();

  }

  bool has(ImSession session) {
    return messageDataChangeListener.getDataByKey(session, (d1, d2)=>d1.id == d2.id) >= 0;
  }

  _calacHotMessageTotal() {
    var hotMessageTotal = 0;
    var total = messageDataChangeListener.getTotal();
    for (var i=0; i<total; i++) {
      hotMessageTotal += (messageDataChangeListener.getData(i).hotMessageTotal??0);
    }
    return hotMessageTotal;
  }

  int get hotMessageTotal => this.hotMessageTotal;
}